/** @file grayimage.h
 * @brief Este arquivo fonte é distíbuido sob a licença GNU/GPL e contém a classe GrayImage e algumas funções para a leitura e gravação de arquivos PGM e inicialização de GrayImage.
 *
 *   Este programa é um software livre. Você pode redistribuí-lo e/ou modificá-lo dentro dos termos da Licença Pública Geral GNU como publicada pela Fundação do Software Livre (FSF); na versão 2 da Licença, ou (na sua opinião) qualquer versão posterior.
 */

#ifndef GRAYIMAGE_H
#define GRAYIMAGE_H
#include "rectsupport.h"
#include <string>
#define P2 2;
#define P5 5;
using namespace std;

/**
 * @brief Permite a manipulação de imagens tons de cinza com pixels pertencentes ao intervalo [0, 255].
 *
 * Os pixels são armazenados em um array de _Rows x _Cols elementos do tipo unsigned char.
 * \sa RectSupport
 * @author Guilherme Lucio Abelha Mota e Grupo de pesquisa Apoena http://dgp.cnpq.br/buscaoperacional/detalhegrupo.jsp?grupo=0326103T3AKW5D#identificacao
 * @version 1.0
 * @date 11/04/2014
 */
class GrayImage : public RectSupport{

private:
   /** @brief Array que armazena os números digitais dos pixels da imagem.
    *
    * O conteúdo de _pixels corresponade à concatenação das linhas da imagem.
    */
    unsigned char* _pixels;

protected:
   /**
    * @brief Esta função deleta o array de pixels.
    */
   void del();

   /**
    * @brief Aloca um array de _Rows x _Cols pixels do tipo unsigned char.
    *
    * Os valores dos números digitais dos pixels são inicializados com zero e _Rows e _Cols são modificados.
    * @param parRows número de linhas da imagem.
    * @param parCols número de colunas da imagem.
    */
   void nw(const unsigned int parRows, const unsigned int parCols);

public:

   /**
    * @brief Construtor da classe GrayImage.
    *
    * Esta versão permite a criação da uma GrayImage com _pixels = NULL e _Rows e _Cols = 0.
    *
    */
   GrayImage();


   /**
    * @brief Construtor da classe GrayImage.
    *
    * Esta versão permite a criação da uma GrayImage com suporte geométrico retangular.
    * @param parRows número de linhas da imagem.
    * @param parCols número de colunas da imagem.
    *
    */
    GrayImage(unsigned int parRows, unsigned int parCols);


    /**
     * @brief Construtor da classe GrayImage.
     *
     * Esta versão é um construtor de cópia.
     * @param parGrayImage imagem a ser copiada.
     *
     */
     GrayImage(GrayImage& parparGrayImage);


    /**
     * @brief Destrutor da classe GrayImage.
     */
    ~GrayImage();


    /**
     * @brief Retorna o número digital do pixel (x, y).
     * @param x linha do pixel.
     * @param y coluna do pixel.
     * @return número digital do pixel.
     */
    unsigned char getPixel(const unsigned int x, const unsigned int y) const;


    /**
     * @brief Muda o número digital do pixel (x, y).
     * @param x linha do pixel.
     * @param y coluna do pixel.
     * @param parValue novo número digital do pixel.
     */
    void setPixel(unsigned int x, unsigned int y, unsigned char parValue) ;


    /**
     * @brief Retorna uma GrayImage correspondente ao recorte uma janela contígua da GrayImage corrente.
     *
     * O intervalo de pixels  [FirstRow, LastRow] x [ FirstCol, LastCol]
     * @param FirstRow primeira linha do recorte.
     * @param LastRow  última linha do recorte.
     * @param FirstCol primeira coluna do recorte.
     * @param LastCol  última coluna do recorte.
     * @return GrayImage do recorte.
     */
    GrayImage cut(const unsigned int FirstRow, const unsigned int LastRow, const unsigned int FirstCol, const unsigned int LastCol);


    /**
     * @brief Operador de atribuição para a classe GrayImage.
     *
     * A imagem corrente passa a ser idêntica à imagem à direita do operador =.
     * @param parMatrix referência para a imagem cujo conteúdo será copiado.
     */
    GrayImage& operator =(const GrayImage& parImage);


    /**
     * @brief Imprime na tela uma versão PGM classe P2 da GrayImage corrente.
     */
    void show() const;
};

/** @fn GrayImage loadPGM(string fileName)
 * @brief Lê uma GrayImage codificada no formato PGM P2.
 *
 * Em caso de erro de E/S o programa é abortado.
 * @param fileName caminho + nome do arquivo.
 * @return GrayImage correspondente à imagem carregada da memória secundária.
 */
GrayImage loadPGM(string fileName);

/** @fn void savePGM(GrayImage parImage, string fileName, int format)
 * @brief Salva uma GrayImage no formato PGM P2 ou P5.
 *
 * Em caso de erro de E/S o programa é abortado.
 * @param parImage imagem tons de cinza a ser gravada na memória secundária.
 * @param fileName caminho + nome do arquivo.
 * @param format 2 para P2. Nesta versão outros valores são inválidos.
 * @param maxValue
 */
 void savePGM(GrayImage parImage, string fileName, int format, unsigned int maxValue);

 /** @fn int getPGMSubformat(string fileName)
  * @brief Lê o cabeçalho do arquivo PGM para verificar se o formato é PGM P2 ou P5.
  *
  * Em caso de erro de E/S o programa é abortado.
  *
  * @param fileName caminho + nome do arquivo.
  * @return 2 for PGM P2 or 5 for PGM P5
  */
 int getPGMSubformat(string fileName);


/** @fn GrayImage blackImage(unsigned int size)
 * @brief Cria uma GrayImage preta de dimensões size x size.
 *
 * Todos os pixels possuem valor zero.
 * @param size número de linhas e colunas da imagem gerada.
 */
 GrayImage blackImage(unsigned int size);

/** @fn GrayImage blackImage(unsigned int parRows, unsigned int parCols)
 * @brief Cria uma GrayImage preta de dimensões parRows x parCols.
 *
 * Todos os pixels possuem valor zero.
 * @param parRows número de linhas da imagem gerada.
 * @param parCols número de colunas da imagem gerada.
 */
 GrayImage blackImage(unsigned int parRows, unsigned int parCols);

#endif
